﻿using System.Collections.Generic;
using System.Linq;
using System.Linq.Dynamic;
using Web.Infrastructure.Mvc.Query.Attributes;

namespace Web.Infrastructure.Mvc.Query
{
    public static class QueryModelExtensions
    {
        public static IList<T> Search<T>(this IQueryable<T> query, object model)
        {
            var properties = model.GetType().GetProperties();
            foreach (var property in properties)
            {
                if (property.PropertyType == typeof(string))
                {
                    var propertyValue = property.GetValue(model) as string;
                    if (!string.IsNullOrEmpty(propertyValue))
                    {
                        query = query.Where("");
                    }
                }
            }

            SetTotalCount(model, query.Count());
            string sortName;
            bool desc;
            GetOrderBy(model, out sortName, out desc);
            var orderedQuery = desc ? query.OrderBy(sortName + " desc") : query.OrderBy(sortName);
            var pageIndex = GetPageIndex(model);
            var pageSize = GetPageSize(model);
            return orderedQuery.Take(pageSize * pageIndex).Skip(pageSize * (pageIndex - 1)).ToList();
        }

        private static void SetTotalCount(object model, int totalCount)
        {
            var property = model.GetType().GetProperties().FirstOrDefault(o => o.CustomAttributes.Any(a => a.AttributeType == typeof(TotalCountAttribute)));
            property.SetValue(model, totalCount);
        }

        private static void GetOrderBy(object model, out string sortName, out bool desc)
        {
            var property = model.GetType().GetProperties().FirstOrDefault(o => o.CustomAttributes.Any(a => a.AttributeType == typeof(OrderByAttribute)));
            var result = (string)property.GetValue(model);
            if (!string.IsNullOrEmpty(result))
            {
                var strs = result.Split('-');
                sortName = strs[0];
                desc = strs[1].ToLower() != "asc";
            }
            else
            {
                sortName = "Id";
                desc = false;
            }
        }

        private static int GetPageIndex(object model)
        {
            var property = model.GetType().GetProperties().FirstOrDefault(o => o.CustomAttributes.Any(a => a.AttributeType == typeof(PageIndexAttribute)));
            var result = (int)property.GetValue(model);
            return result;
        }

        private static int GetPageSize(object model)
        {
            var property = model.GetType().GetProperties().FirstOrDefault(o => o.CustomAttributes.Any(a => a.AttributeType == typeof(PageSizeAttribute)));
            var result = (int)property.GetValue(model);
            return result;
        }
    }
}